import org.lwjgl.opengl.*;
import org.lwjgl.util.glu.*;
import org.lwjgl.input.Keyboard;

//City View with stationary window
public class City {
    private boolean done = false; //main loop bool
    
    //Booleans keeping track of key presses
    private boolean spaceDown=false;
    
    private boolean upDown=false;
    private boolean downDown=false;
    private boolean leftDown=false;
    private boolean rightDown=false;
    
    private boolean wDown=false;
    private boolean aDown=false;
    private boolean sDown=false;
    private boolean dDown=false;
    
    private final String windowTitle = "Adam's App"; //Display title on window
    private DisplayMode displayMode;
 	float x1=0f; // x position of camera
 	float x2=0f; // x target of camera
 	float y1=0f; // y position of camera;
 	float y2=0f; // y target of camera
 	float z1=15f; //z position of camera
 	float z2=7f; //z target of camera
 	float rotation=0f;// How much the camera is rotated away from origin


    //Main function just creates and runs the application.
    public static void main(String args[]) {
    	City app = new City();
        app.run();
    }


    //Initialize the app, then sit in a render loop until done.
    public void run() {
        try {
            init();
            while (!done) {
                keyboardInput();
                render();
                Display.update();

            }
            Display.destroy();
        }
        catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }


    //Initialize the environment: @throws Exception   
    private void init() throws Exception {
        initDisplay();
        initGL();
    }

    //Create an OpenGL display, in this case a fullscreen window. @throws Exception    
    private void initDisplay() throws Exception {
        
    	// set to full screen, no chrome
        Display.setFullscreen(false);
        
        // get all possible display resolutions
        DisplayMode[] d = Display.getAvailableDisplayModes();
        
        // find a resolution we like
        for (int i = 0; i < d.length; i++) {
            if (d[i].getWidth() == 800
                && d[i].getHeight() == 600
                && d[i].getBitsPerPixel() == 32) {
                displayMode = d[i];
                break;
            }
        }
        // set the display to the resolution we picked
        Display.setDisplayMode(displayMode);
        //Set message on top of screen
        Display.setTitle(windowTitle);
        // create the window
        Display.create();
    }

  
    //Initialize OpenGL
    private void initGL() {
    	
        // Select the Projection Matrix (controls perspective)
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        	
        GL11.glLoadIdentity(); // Reset The Projection Matrix

        // Define perspective
        GLU.gluPerspective(
            45.0f,        // Field Of View
            (float)displayMode.getWidth() / (float)displayMode.getHeight(), // aspect ratio
            0.1f,         // near Z clipping plane
            100.0f);      // far Z clipping plane



        // Select The Modelview Matrix (controls model orientation)
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        
        // depth
        GL11.glEnable(GL11.GL_DEPTH_TEST);
    }


    //Handle keyboard input.  Checks lots of keys, check the list of booleans to see which are checked
    private void keyboardInput() {
    	
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
    		spaceDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
    		spaceDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)){
    		leftDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_LEFT)){
    		leftDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)){
    		rightDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_RIGHT)){
    		rightDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)){
    		downDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_DOWN)){
    		downDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_UP)){
    		upDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_UP)){
    		upDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_W)){
    		wDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_W)){
    		wDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_A)){
    		aDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_A)){
    		aDown=false;}
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_S)){
    		sDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_S)){
    		sDown=false;}    
    	
    	if(Keyboard.isKeyDown(Keyboard.KEY_D)){
    		dDown=true;}
    	else if(!Keyboard.isKeyDown(Keyboard.KEY_D)){
    		dDown=false;}
    	
    	
        if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {   // Escape is pressed
            done = true;
        }
        if(Display.isCloseRequested()) {                // Window is closed
            done = true;
        }
    }

    //Render the Scene
    private void render() {
        // Clear screen and depth buffer
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        // Reset the Modelview matrix
        // this resets the coordinate system to center of screen
        GL11.glLoadIdentity();
        double zLine=z2-z1;
        double xLine=x2-x1;
        if(upDown && z1>7f){
        	if(rotation==0){
        		z1-=.01f;
        		z2-=.01f;
        	}
        	else if(rotation <=Math.PI/2 ){
        		z1-=Math.cos(rotation)*.01f;
        		z2-=Math.cos(rotation)*.01f;
        		x1+=Math.sin(rotation)*.01f;
        		x2+=Math.sin(rotation)*.01f;
        	}
        }
        if(downDown){
        	if(rotation==0){	
        		z1+=.01f;
        		z2+=.01f;
        	}
        	else if(Math.toDegrees(rotation) <=90){
        		z1+=Math.cos(rotation)*.01f;
        		z2+=Math.cos(rotation)*.01f;
        		x1-=Math.sin(rotation)*.01f;
        		x2-=Math.sin(rotation)*.01f;
        		
        	}
        }
        if(leftDown){
        	x1-=.01f;
        	x2-=.01f;}
        if(rightDown){
        	x1+=.01f;
        	x2+=.01f;}
        
        if(wDown){
        	y1+=.01f;
        	y2+=.01f;}
        if(sDown){
        	y1-=.01f;
        	y2-=.01f;}
        
        if(aDown){
        	if(xLine==0){
        		if(zLine<=0){
        			x2-=.01;
        			z2+=.01;
        		}
        		if(zLine>0){
        			x2+=.01;
        			z2+=.01;
        		}
        	}
        	if(xLine<0){
        		if(zLine<=0){
        			x2+=.01;
        			z2+=.01;
        		}
        		if(zLine>0){
        			x2-=.01;
        			z2-=.01;
        		}
        	}
        	if(xLine>0){
        		if(zLine<=0){
        			x2-=.01;
        			z2+=.01;
        		}
        		if(zLine>0){
        			x2+=.01;
        			z2+=.01;
        		}
        	}
        	x2-=.01;
        	z2-=.01;
        	rotation=(float) Math.toDegrees(Math.atan((z2-z1)/(x2-x1)));
        	
        	String x=""+rotation+" " + xLine + " " + zLine;
        	System.out.println(x);
        }
        if(dDown){
        	if(xLine==0){
        		if(zLine>=0){
        			x2-=.01;
        			z2+=.01;
        			System.out.println("cake");
        		}
        		if(zLine<0){
        			x2+=.01;
        			z2+=.01;
        		}
        	}
        	if(xLine<0){
        		if(zLine>=0){
        			x2+=.01;
        			z2+=.01;
        		}
        		if(zLine<0){
        			x2-=.01;
        			z2-=.01;
        		}
        	}
        	if(xLine>0){
        		if(zLine>=0){
        			x2-=.01;
        			z2+=.01;
        		}
        		if(zLine<0){
        			x2+=.01;
        			z2+=.01;
        		}
        	}
        	//x2+=.01;
        	//z2+=.01;
        	rotation=(float) Math.toDegrees(Math.atan((z2-z1)/(x2-x1)));
        	
        	String x=""+rotation+" " + xLine + " " + zLine;
        	System.out.println(x);
        }

      
        GLU.gluLookAt(
                x1, y1, z1,      //
                x2, y2, z2,   // target to look at (Origin)
                0f, 1f, 0f);   // which way is up 
        
       
        

        for(int a=0; a<50; a++){
        	GL11.glPushMatrix();
        	GL11.glTranslatef(-25, 0, a*10);
        	renderCube(50f, .1f, .1f);
        	GL11.glPopMatrix();
        }
		//Draw Center Cube
       // GL11.glColor3f(.6f,.6f,.6f);
      //  renderCube(.6f,1f, .2f);
        
      /*  GL11.glPushMatrix();
		{
			GL11.glColor3f(.6f,.6f,.6f);
			GL11.glTranslatef(5, 0, 0);
			renderCube(1f,1f, 1f);	        
		}
        GL11.glPopMatrix();
        
        GL11.glPushMatrix();
		{
			GL11.glColor3f(.3f,.3f,.3f);
			GL11.glTranslatef(0, 0, 5);
			renderCube(1f,1f, 1f);	        
		}
        GL11.glPopMatrix();*/

    }

    
    //Renders a Cube whose 3 dimensions are scalable
    public void renderCube(float scalex, float scaley, float scalez)
    {
    	GL11.glPushMatrix();
    	{
    		GL11.glScalef(scalex,scaley,scalez);
    		GL11.glBegin(GL11.GL_QUADS);
    		// Front Face
    		GL11.glVertex3f(-1.0f, -1.0f,  1.0f);	// Bottom Left
    		GL11.glVertex3f( 1.0f, -1.0f,  1.0f);	// Bottom Right
    		GL11.glVertex3f( 1.0f,  1.0f,  1.0f);	// Top Right
    		GL11.glVertex3f(-1.0f,  1.0f,  1.0f);	// Top Left
    		// Back Face
    		GL11.glVertex3f(-1.0f, -1.0f, -1.0f);	// Bottom Right
    		GL11.glVertex3f(-1.0f,  1.0f, -1.0f);	// Top Right
    		GL11.glVertex3f( 1.0f,  1.0f, -1.0f);	// Top Left
    		GL11.glVertex3f( 1.0f, -1.0f, -1.0f);	// Bottom Left
    		// Top Face
    		GL11.glVertex3f(-1.0f,  1.0f, -1.0f);	// Top Left
    		GL11.glVertex3f(-1.0f,  1.0f,  1.0f);	// Bottom Left
    		GL11.glVertex3f( 1.0f,  1.0f,  1.0f);	// Bottom Right
    		GL11.glVertex3f( 1.0f,  1.0f, -1.0f);	// Top Right
    		// Bottom Face
    		GL11.glVertex3f(-1.0f, -1.0f, -1.0f);	// Top Right
    		GL11.glVertex3f( 1.0f, -1.0f, -1.0f);	// Top Left
    		GL11.glVertex3f( 1.0f, -1.0f,  1.0f);	// Bottom Left
    		GL11.glVertex3f(-1.0f, -1.0f,  1.0f);	// Bottom Right
    		// Right face
    		GL11.glVertex3f( 1.0f, -1.0f, -1.0f);	// Bottom Right
    		GL11.glVertex3f( 1.0f,  1.0f, -1.0f);	// Top Right
    		GL11.glVertex3f( 1.0f,  1.0f,  1.0f);	// Top Left
    		GL11.glVertex3f( 1.0f, -1.0f,  1.0f);	// Bottom Left
    		// Left Face
    		GL11.glVertex3f(-1.0f, -1.0f, -1.0f);	// Bottom Left
    		GL11.glVertex3f(-1.0f, -1.0f,  1.0f);	// Bottom Right
    		GL11.glVertex3f(-1.0f,  1.0f,  1.0f);	// Top Right
    		GL11.glVertex3f(-1.0f,  1.0f, -1.0f);	// Top Left
    		GL11.glEnd();
    	}
    	GL11.glPopMatrix();
    }
    

    //Cleanup Resources
}